<!-- Licensed under a BSD license. See license.html for license -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>WebGL2 - precision - lowp, mediump, highp</title>
<link type="text/css" href="resources/webgl-tutorials.css" rel="stylesheet" />
<style>
  table {
    border-collapse: collapse;
  }
  thead {
    background: lightcoral;
  }
  th, td {
    border: 1px solid black;
    padding: 0.2em;
  }
  .shader-type {
    background: lightseagreen;
  }
  .no-support {
    background: red;
    color: white;
  }
</style>
</head>
<body>
</body>
<!--
for most samples webgl-utils only provides shader compiling/linking and
canvas resizing because why clutter the examples with code that's the same in every sample.
See https://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html
and https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
for webgl-utils, m3, m4, and webgl-lessons-ui.
-->
<script src="resources/webgl-utils.js"></script>
<script>
"use strict";

function main() {
  // Get A WebGL context
  /** @type {HTMLCanvasElement} */
  const canvas = document.createElement("canvas");
  const gl = canvas.getContext("webgl2");
  if (!gl) {
    return;
  }

  const shaderTypes = [
    'VERTEX_SHADER',
    'FRAGMENT_SHADER',
  ];
  const precisionTypes = [
    'LOW_FLOAT',
    'MEDIUM_FLOAT',
    'HIGH_FLOAT',
    'LOW_INT',
    'MEDIUM_INT',
    'HIGH_INT',
  ];

  const tbody = createTable(document.body, ['type', 'bits', 'precision', 'min', 'max']);
  for (const shaderType of shaderTypes) {
    const tr = addElem('tr', tbody);
    addElem('td', tr, {
      textContent: shaderType,
      colSpan: 5,
      className: 'shader-type',
    });
    for (const precisionType of precisionTypes) {
      const tr = addElem('tr', tbody);
      const format = gl.getShaderPrecisionFormat(gl[shaderType], gl[precisionType]);
      const isInt = format.precision === 0;
      const bits = isInt
         ? format.rangeMin + 1
         : format.precision + Math.log2(format.rangeMin + 1) + 2;

      addElem('td', tr, {
        textContent: precisionType.toLowerCase().replace('_', 'p '),
      });
      addElem('td', tr, {textContent: bits});
      addElem('td', tr, {textContent: format.precision});
      addElem('td', tr, {textContent: format.rangeMin});
      addElem('td', tr, {textContent: format.rangeMax});
    }
  }
}

function addElem(tag, parent, attrs = {}) {
  const elem = createElem(tag, attrs);
  parent.appendChild(elem);
  return elem;
}

function createTable(parent, headings) {
  const table = addElem('table', parent);
  const thead = addElem('thead', table);
  headings.forEach(heading => addElem('th', thead, {textContent: heading}));
  return addElem('tbody', table);
}

function createElem(tag, attrs = {}) {
  const elem = document.createElement(tag);
  for (const [key, value] of Object.entries(attrs)) {
    if (typeof value === 'object') {
      for (const [k, v] of Object.entries(value)) {
        try {
        elem[key][k] = v;
        } catch (e) {
          debugger;  // eslint-disable-line no-debugger
        }
      }
    } else if (elem[key] === undefined) {
      elem.setAttribute(key, value);
    } else {
      elem[key] = value;
    }
  }
  return elem;
}

main();
</script>
</html>


